package com.lc.ibps.web.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lc.ibps.api.base.cache.ICache;
import com.lc.ibps.api.base.constants.StateEnum;
import com.lc.ibps.api.base.model.PartyEmployee;
import com.lc.ibps.api.base.model.User;
import com.lc.ibps.api.org.service.IPartyEmployeeService;
import com.lc.ibps.api.org.service.IPartyEntityService;
import com.lc.ibps.api.org.service.IPartyPositionService;
import com.lc.ibps.api.org.service.IPartyUserService;
import com.lc.ibps.api.tenant.service.ITenantQueryService;
import com.lc.ibps.base.core.util.AppUtil;
import com.lc.ibps.base.core.util.BeanUtils;
import com.lc.ibps.base.core.util.JacksonUtil;
import com.lc.ibps.base.core.util.string.StringUtil;
import com.lc.ibps.base.framework.persistence.entity.AbstractPo;
import com.lc.ibps.base.web.context.ContextUtil;
import com.lc.ibps.base.web.context.RequestContext;
import com.lc.ibps.base.web.handler.SecurityUrlHandler;
import com.lc.ibps.base.web.util.RequestUtil;
import com.lc.ibps.cloud.constants.ParameterKey;
import com.lc.ibps.cloud.entity.APIResult;
import com.lc.ibps.components.httpclient.model.HttpStatus;
import com.lc.ibps.components.token.model.CommonResult;
import com.lc.ibps.components.token.model.Token;
import com.lc.ibps.components.token.model.TokenResult;
import com.lc.ibps.components.token.util.ValidUtil;
import com.lc.ibps.org.party.persistence.entity.DefaultPartyUserPo;
import com.lc.ibps.org.party.persistence.entity.PartyEmployeePo;
import com.lc.ibps.org.party.persistence.entity.PartyOrgPo;
import com.lc.ibps.org.party.persistence.entity.PartyPositionPo;
import com.lc.ibps.platform.rest.token.TokenUtil;

import net.sf.json.JSONObject;

/**
 * Token过滤器。
 *
 * <pre>
 *  
 * 构建组：ibps-platform-webapi
 * 作者：hugh zhuang
 * 邮箱：3378340995@qq.com
 * 日期：2016年5月17日-上午9:40:28
 * 版权：广州流辰信息技术有限公司版权所有
 * </pre>
 */
public class TokenFilter implements Filter {

	protected Logger logger = LoggerFactory.getLogger(getClass());

	public static final String IBPS_ADMIN_TOKEN = "IBPS-ADMIN-TOKEN";

	public static final String IBPS_ADMIN_ACCOUNT = "IBPS-ADMIN-ACCOUNT";

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@SuppressWarnings("unchecked")
	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {

		HttpServletRequest request = (HttpServletRequest) servletRequest;
		ICache<String> cache = AppUtil.getBean(ICache.class);

		APIResult<String> apiResult = new APIResult<String>();
		// 通过头 获取token
		String token = request.getHeader(ParameterKey.HEADER_AUTHORIZATION);
		if (BeanUtils.isEmpty(token)) {// 从url 里面携带
			token = request.getParameter(ParameterKey.FORM_ACCESS_TOKEN);
		}
		//都取不到 去cookie  里面取 
		if (BeanUtils.isEmpty(token)) {
			Cookie[] cookies = request.getCookies();
			for (Cookie cookie : cookies) {
				if(cookie.getName().equals(IBPS_ADMIN_TOKEN)){
					token =  cookie.getValue();
					break;
				}
			}
		}
		String url = removeCtx(request.getRequestURI(), request.getContextPath());

		SecurityUrlHandler securityUrlHandler = (SecurityUrlHandler) AppUtil.getBean(SecurityUrlHandler.class);
		// 是否匿名
		boolean isAnony = securityUrlHandler.isAnonymousAccess(url);

		if (isAnony) {// 匿名
			CommonResult commonResult = ValidUtil.validToken(token);
			if (HttpStatus.OK.value() != commonResult.getCode()) { // 验证失败，返回
				apiResult.setState(StateEnum.ILLEGAL_TOKEN.getCode());
			} else {
				TokenResult tokenResult = (TokenResult) commonResult;
				if (tokenResult.getType() == Token.TOKEN_ANONYMOUS) {
					// TODO
				}
			}
		} else { // 需要登录
			CommonResult commonResult = ValidUtil.validToken(token);

			if (HttpStatus.OK.value() != commonResult.getCode()) { // 验证失败，返回
				apiResult.setState(StateEnum.ILLEGAL_TOKEN.getCode());
			} else {
				TokenResult tokenResult = (TokenResult) commonResult;
				if (tokenResult.getType() == Token.TOKEN_FORMAL) {
					try {

						// 获取缓存的key，并根据key获取用户名
						String userKey = TokenUtil.getKey(token);
						String account = (String) cache.getByKey(userKey);

						IPartyUserService partyUserService = AppUtil.getBean(IPartyUserService.class);
						User user = DefaultPartyUserPo.fromJsonString2(partyUserService.getByAccountJson(account));

						if (BeanUtils.isEmpty(user)) {
							apiResult.setState(StateEnum.ILLEGAL_TOKEN.getCode());
						} else {
							// 设置用户上下文信息
							cacheUserInfo(token, user);
						}
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
						apiResult.setState(StateEnum.ILLEGAL_TOKEN.getCode());
					}
				} else {
					apiResult.setState(StateEnum.ILLEGAL_TOKEN.getCode());
				}
			}
		}

		if (StateEnum.SUCCESS.getCode() == apiResult.getState()) {
			chain.doFilter(request, response);
		} else {
			response.getWriter().println(JSONObject.fromObject(apiResult).toString());
		}
	}

	@Override
	public void destroy() {
	}

	/**
	 * 获取当前URL
	 * 
	 * @param url
	 * @param contextPath
	 * @return
	 */
	private static String removeCtx(String url, String contextPath) {
		url = url.trim();
		if (StringUtil.isEmpty(contextPath))
			return url;
		if (StringUtil.isEmpty(url))
			return "";
		if (url.startsWith(contextPath)) {
			url = url.replaceFirst(contextPath, "");
		}
		return url;
	}

	/**
	 * 设置线程缓存数据
	 *
	 * @param accessToken
	 * @param user
	 */
	@SuppressWarnings("unchecked")
	protected void cacheUserInfo(String accessToken, User user) {
		logger.debug("set context info.");

		String ip = RequestUtil.getIpAddr(RequestContext.getHttpServletRequest());
		((AbstractPo<String>) user).setIp(ip);
		// Context当前用户
		ContextUtil.setCurrentUser(user);

		// Context当前组织
		IPartyEmployeeService partyEmployeeService = AppUtil.getBean(IPartyEmployeeService.class);
		String data = partyEmployeeService.getByIdJson(user.getUserId());
		PartyEmployee employee = PartyEmployeePo.fromJsonString(data);
		if (BeanUtils.isNotEmpty(employee) && StringUtil.isNotEmpty(employee.getGroupID())) {
			IPartyEntityService partyEntityService = AppUtil.getBean(IPartyEntityService.class);
			String orgData = partyEntityService.getByIdJson(employee.getGroupID());
			if (JacksonUtil.isJsonObject(orgData)) {
				PartyOrgPo org = JacksonUtil.getDTO(orgData, PartyOrgPo.class);
				ContextUtil.setCurrentOrg(org);
			}
		}

		// Context当前主岗位
		IPartyPositionService partyPositionService = AppUtil.getBean(IPartyPositionService.class);
		String pdata = partyPositionService.getMainPostByUserId(user.getUserId());
		if (JacksonUtil.isJsonObject(pdata)) {
			PartyPositionPo position = JacksonUtil.getDTO(pdata, PartyPositionPo.class);
			ContextUtil.setCurrentPosition(position);
		}

		ContextUtil.setCurrentUserIp(ip);

		// 获取当前用户的租户信息并添加到线程
		ITenantQueryService tenantQueryService = AppUtil.getBean(ITenantQueryService.class);
		if (AppUtil.isTenant() && null != tenantQueryService) {
			String tenantId = tenantQueryService.getTenantId(user.getUserId());
			ContextUtil.setCurrentTenantId(tenantId);
			logger.debug("set context tenant id {}.", tenantId);
			String tenantIds = tenantQueryService.getTenantIds(user.getUserId());
			ContextUtil.setCurrentTenantIds(tenantIds);
			logger.debug("set context tenants id {}.", tenantIds);
		}

		// 保存本地线程数据
		ContextUtil.setCurrentAccessToken(accessToken);
	}

}
